﻿using Microsoft.VisualBasic.CompilerServices;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;

namespace SampleClient
{
    class Program
    {
        private static readonly HttpClient client = new HttpClient();

        private static string BaseUrl = "https://localhost:44316/";
        private static string Token;

        static void Main(string[] args)
        {
            //TestControllerFilter();
            TestActionFilter();

            Console.ReadLine();
        }

        private static void TestControllerFilter()
        {
            Console.WriteLine("Start Get User List(No Token):");
            var lst = GetUserList("User");
            PrintUserList(lst);
            Console.WriteLine("End   Get User List(No Token):");
            Console.WriteLine("");

            Console.WriteLine("Start Get Token:");
            Token = SignIn("alice", "alice");
            if (Token == string.Empty)
            {
                Console.WriteLine("SignIn Failed.");
            }
            else
            {
                Console.WriteLine("SignIn Sucess.");
            }
            Console.WriteLine("End   Get Token:");
            Console.WriteLine("");

            Console.WriteLine("Start Get User List:");
            lst = GetUserList();
            PrintUserList(lst);
            Console.WriteLine("End   Get User List:");
            Console.WriteLine("");
        }

        private static void TestActionFilter()
        {
            Console.WriteLine("Start Get User List(No Token):");
            var lst = GetUserList();
            PrintUserList(lst);
            Console.WriteLine("End   Get User List(No Token):");
            Console.WriteLine("");

            Console.WriteLine("Start Get Token:");
            Token = SignIn("alice", "alice");
            if (Token == string.Empty)
            {
                Console.WriteLine("SignIn Failed.");
            }
            else
            {
                Console.WriteLine("SignIn Sucess.");
            }
            Console.WriteLine("End   Get Token:");
            Console.WriteLine("");

            Console.WriteLine("Start Get User List:");
            lst = GetUserList();
            PrintUserList(lst);
            Console.WriteLine("End   Get User List:");
            Console.WriteLine("");

            Console.WriteLine("Start Get User :");
            var obj = GetUser("2");
            if (obj != null)
            {
                Console.WriteLine($"Id: {obj.Id}, Name: {obj.Name},Id: {obj.Password}. ");
            }
            Console.WriteLine("End   Get User :");
            Console.WriteLine("");


            Console.WriteLine("Start Add User :");
            User newUser = new User { Id = 3, Name = "tester", Password = "tester", Role = "Operator", Email = "tester@gmail.com", PhoneNumber = "18800000003", Birthday = DateTime.Now };
            Console.WriteLine($"Result: { AddUser(newUser)}.");
            lst = GetUserList();
            PrintUserList(lst);
            Console.WriteLine("End   Add User :");
            Console.WriteLine("");


            Console.WriteLine("Start Update User :");
            obj.Password = "password";
            Console.WriteLine($"Result: { UpdateUser(obj)}.");
            lst = GetUserList();
            PrintUserList(lst);
            Console.WriteLine("End   Update User :");
            Console.WriteLine("");


            Console.WriteLine("Start Delete User :");
            Console.WriteLine($"Result: { DeleteUser(obj.Id)}.");
            lst = GetUserList();
            PrintUserList(lst);
            Console.WriteLine("End   Delete User :");
            Console.WriteLine("");
        }

        private static void PrintUserList(List<User> userList)
        {
            foreach (var item in userList)
            {
                Console.WriteLine($"Id: {item.Id}, Name: {item.Name},Password: {item.Password}. ");
            }
        }
       
        private static string SignIn(string userName, string password)
        {
            try
            {
                var user = new UserDto()
                {
                    UserName = userName,
                    Password = password
                };

                var json = JsonConvert.SerializeObject(user);
                var data = new StringContent(json, Encoding.UTF8, "application/json");


                var url = $"{BaseUrl}TestAuthenticate/SignIn";

                //Console.WriteLine($"{url}");
                var response = client.PostAsync(url, data).Result;

                var responseString = response.Content.ReadAsStringAsync().Result;
                var jsonobj = JsonConvert.DeserializeObject<TokenObject>(responseString);

                if (jsonobj == null || jsonobj.access_token == null)
                {
                    Console.WriteLine($"SignIn Failed: {response.StatusCode}");
                    return string.Empty;
                }
                else
                {
                    return jsonobj.access_token;
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"SignIn Exception: {ex.Message}");
                return string.Empty;
            }
        }

        private static List<User> GetUserList(string controllerName = "TestAuthenticate")
        {
            try
            {
                var url = $"{BaseUrl}{controllerName}";
                if (!string.IsNullOrEmpty(Token))
                {
                    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", Token);
                }

                var response = client.GetAsync(url).Result;
                
                if (response.IsSuccessStatusCode)
                {
                    var responseString = response.Content.ReadAsStringAsync().Result;
                    var userList = JsonConvert.DeserializeObject<List<User>>(responseString);
                    return userList;
                }
                else
                {
                    Console.WriteLine($"GetUserList Http Status Code: {response.StatusCode}");
                    return new List<User>();
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"GetUserList Exception: {ex.Message}");
                return new List<User>();
            }
        }

        private static User GetUser(string id, string controllerName = "TestAuthenticate")
        {
            try
            {
                var url = $"{BaseUrl}{controllerName}/{id}";
                if (!string.IsNullOrEmpty(Token))
                {
                    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", Token);
                }

                var response = client.GetAsync(url).Result;
                if (response.IsSuccessStatusCode)
                {
                    var responseString = response.Content.ReadAsStringAsync().Result;
                    var user = JsonConvert.DeserializeObject<User>(responseString);
                    return user;
                }
                else
                {
                    Console.WriteLine($"GetUser Http Status Code: {response.StatusCode}");
                    return null;
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"GetUser Exception: {ex.Message}");
                return null;
            }
        }

        private static bool AddUser(User user)
        {
            try
            {
                var url = $"{BaseUrl}TestAuthenticate/AddUser";
                if (!string.IsNullOrEmpty(Token))
                {
                    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", Token);
                }

                var json = JsonConvert.SerializeObject(user);
                var data = new StringContent(json, Encoding.UTF8, "application/json");


                var response = client.PostAsync(url, data).Result;
                if (response.IsSuccessStatusCode)
                {
                    return true;
                }
                else
                {
                    Console.WriteLine($"AddUser Http Status Code: {response.StatusCode}");
                    return false;
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"AddUser Exception: {ex.Message}");
                return false;
            }
        }

        private static bool UpdateUser(User user)
        {
            try
            {
                var url = $"{BaseUrl}TestAuthenticate/{user.Id}";
                if (!string.IsNullOrEmpty(Token))
                {
                    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", Token);
                }

                var json = JsonConvert.SerializeObject(user);
                var data = new StringContent(json, Encoding.UTF8, "application/json");


                var response = client.PutAsync(url, data).Result;
                if (response.IsSuccessStatusCode)
                {
                    return true;
                }
                else
                {
                    Console.WriteLine($"UpdateUser Http Status Code: {response.StatusCode}");
                    return false;
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"UpdateUser Exception: {ex.Message}");
                return false;
            }
        }

        private static bool DeleteUser(int id)
        {
            try
            {
                var url = $"{BaseUrl}TestAuthenticate/{id}";
                if (!string.IsNullOrEmpty(Token))
                {
                    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", Token);
                }

                var response = client.DeleteAsync(url).Result;
                if (response.IsSuccessStatusCode)
                {
                    return true;
                }
                else
                {
                    Console.WriteLine($"DeleteUser Http Status Code: {response.StatusCode}");
                    return false;
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"DeleteUser Exception: {ex.Message}");
                return false;
            }
        }
    }

    public class UserDto
    {
        public string UserName { get; set; }

        public string Password { get; set; }
    }

    public class TokenObject
    {
        public string access_token { get; set; }

        public string token_type { get; set; }

        public Profile profile { get; set; }
    }

    public class Profile
    {
        public string sid { get; set; }

        public string name { get; set; }
        public string auth_time { get; set; }
        public string expires_at { get; set; }
    }

    public class User
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Role { get; set; }
        public string Email { get; set; }
        public string PhoneNumber { get; set; }
        public string Password { get; set; }
        public DateTime Birthday { get; set; }
    }
}
